package se581.banker.manager.impl;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import org.apache.log4j.Logger;

import se581.banker.BankerConstants.TrackerEventType;
import se581.banker.TrackerAccount;
import se581.banker.dao.AccountQueryDao;
import se581.banker.dao.TrackerDao;
import se581.banker.event.EventFactory;
import se581.banker.event.TrackerEvent;
import se581.banker.manager.AccountTracker;

/**
 * This AccountTracker implementation handles client query requests
 * 
 * @author mmichalak
 *
 */
public class InquiryTracker implements AccountTracker {
	static Logger logger = Logger.getLogger(InquiryTracker.class.getName());

	AccountQueryDao dao = null;
	
	int socketPort = -1;
	

	@Override
	public String processRequest(TrackerEvent ev) {
		logger.debug("Beginning processRequest for Query");
		
		String response = null;
		TrackerEventType query = ev.getEventType();
		
		if (query == TrackerEventType.BALANCE) {
			response = queryBalance(ev);
		}
		else if (query == TrackerEventType.WHEREIS) {
			response = queryWhereIs(ev);
		}
		else if (query == TrackerEventType.HISTORY) {
			response = queryHistory(ev);
		}
		else if (query == TrackerEventType.LASTUPDATE) {
			response = queryLastUpdate(ev);
		}
		
		return response;
	}
	
	private String queryWhereIs(TrackerEvent ev) {
		String ret = null;
/*		ArrayList<AccountTransaction> locs = dataStore.get(ev.getId());
		if (locs == null || locs.size() == 0) {
			ret = "WHEREIS QUERY: id not found - " + ev.getId();
			logger.debug("--------------------> "+ ret);
			return ret;
		}
		
		AccountTransaction loc = locs.get( locs.size()-1 );
		StringBuilder sb = new StringBuilder(30);
		sb.append(ev.getTick()).append(" QUERY WHEREIS ").append(ev.getId()).append(" ")
			.append(loc.getTransactionAmt());
		
		logger.debug("--------------------> WHEREIS QUERY:  " + sb.toString());
		return sb.toString();*/
		return null;
	}
	
	private String queryHistory(TrackerEvent ev) {
/*		String ret = null;
		ArrayList<AccountTransaction> locs = dataStore.get(ev.getId());
		if (locs == null || locs.size() == 0) {
			ret = "HISTORY QUERY: id not found - " + ev.getId();
			logger.debug("--------------------> " + ret);
			return ret;
		}
		
		StringBuilder sb = new StringBuilder(30);
		sb.append(ev.getTick()).append(" QUERY HISTORY ").append(ev.getId()).append("\n ");
		for (AccountTransaction loc : locs) {
			sb.append(ev.getTick()).append(" ").append(loc.getTransactionAmt()).append("\n ");			
		}
		
		logger.debug("--------------------> HISTORY QUERY:  " + sb.toString());
		return sb.toString();*/
		return null;
	}
	
	private String queryLastUpdate(TrackerEvent ev) {
		/*String ret = null;
		ArrayList<AccountTransaction> locs = dataStore.get(ev.getId());
		if (locs == null || locs.size() == 0) {
			ret = "WHEREIS LASTUPDATE: id not found - " + ev.getId();
			logger.debug("--------------------> " + ret);
			return ret;
		}
		
		AccountTransaction loc = locs.get( locs.size()-1 );
		StringBuilder sb = new StringBuilder(30);
		sb.append(ev.getTick()).append(" QUERY LASTUPDATE ").append(ev.getId()).append(" ")
			.append(loc.getTick()).append(" ").append(loc.getTransactionAmt());
		
		logger.debug("--------------------> LASTUPDATE:  " + sb.toString());
		return sb.toString();*/
		return null;
	}

	private String queryBalance(TrackerEvent ev) {
		String ret = null;
		
		TrackerAccount acct = null;
		
		try {
			acct = dao.findBalanceByPrimaryKey(ev.getId());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if (acct == null) {
			ret = "BALANCE: id not found - " + ev.getId();
			logger.debug("BALANCE: id not found - " + ev.getId());
			return ret;
		}
		
		StringBuilder sb = new StringBuilder(30);
		sb.append(ev.getTick()).append(" QUERY BALANCE ").append(ev.getId()).append(" ");
		sb.append(acct.getBalance());
		
		logger.debug("--------------------> BALANCE QUERY:  " + sb.toString());
		return sb.toString();
	}	


	@Override
	public void run() {
		logger.debug("Starting InquiryTracker instance on port " + socketPort); 

		try {
			String eventLine;
			  
			  ServerSocket welcomeSocket = new ServerSocket(socketPort);
			  welcomeSocket.setReuseAddress(true);

			  while(true) 
			  {
			     Socket connectionSocket = welcomeSocket.accept();
			     connectionSocket.setReuseAddress(true);

			     BufferedReader inFromClient =
			        new BufferedReader(
			        new InputStreamReader(
			        connectionSocket.getInputStream()));

			     DataOutputStream outToClient =
			        new DataOutputStream(
			        connectionSocket.getOutputStream());

			    try {
			    	eventLine = inFromClient.readLine();
				} catch (SocketException e) {
					// Client reset socket
					logger.warn("SocketException caught.  Client reset socket.");
				    continue;
				}
				 logger.debug("rec'd:  " + eventLine);

			     TrackerEvent ev = EventFactory.createEvent(eventLine);
			     String queryRet = processRequest(ev);
			     
			     outToClient.writeBytes(queryRet + '\n');
			     
			  }
		} catch (IOException e) {
			logger.error("Error in InquiryTracker thread");
			e.printStackTrace();
		}
	}

	public int getSocketPort() {
		return socketPort;
	}

	public void setSocketPort(int socketPort) {
		this.socketPort = socketPort;
	}


	public void setDao(TrackerDao dao) {
		this.dao = (AccountQueryDao)dao;
	}

}
